package fun._6742.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import fun._6742.exception.CustomException;
import fun._6742.mapper.ProductMapper;
import fun._6742.model.dataobject.ProductDO;
import fun._6742.model.valueobject.ProductVO;
import fun._6742.request.ConfirmOrderRequest;
import fun._6742.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author LiuQ
 * @since 2022-09-21
 */
@Slf4j
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductDO> implements ProductService {

    @Resource
    ProductMapper productMapper;

    @Override
    public List<ProductDO> lockStock(ConfirmOrderRequest confirmOrderRequest) {
        //        锁定商品库存
        Map<Long, Integer> productNums = confirmOrderRequest.getProductIdAndNums();
        Set<Long> idSet = productNums.keySet();
        List<ProductDO> productDOList = listByIds(idSet);
        for (ProductDO productDO : productDOList) {
            productDO.setLockStock(productNums.get(productDO.getId()) + productDO.getLockStock());
        }
        updateBatchById(productDOList);
        return productDOList;
    }

    @Override
    public Map<String, Integer> findAllBrand() {
        return productMapper.selectList(new QueryWrapper<ProductDO>().select("brand")).stream()
                .map(ProductDO::getBrand)
                .collect(Collectors.toMap(Function.identity(), v -> 1, Integer::sum));
    }

    @Override
    public Map<String, Object> findPageByBrand(String brand, int pageIndex, int pageSize) {
        IPage<ProductDO> productDOPage = page(new Page<>(pageIndex, pageSize), new QueryWrapper<ProductDO>().eq("brand", brand));
        Map<String, Object> map = new HashMap<>(3);
        map.put("total_page", productDOPage.getPages());
        map.put("total_record", productDOPage.getTotal());
        map.put("data", productDOPage.getRecords().stream().map(obj -> {
            ProductVO vo = new ProductVO();
            BeanUtil.copyProperties(obj, vo);
            vo.setStock(obj.getStock() - obj.getLockStock());
            return vo;
        }).collect(Collectors.toList()));
        return map;
    }

    @Override
    public Map<String, Object> findPage(int pageIndex, int pageSize) {
        IPage<ProductDO> productDOPage = page(new Page<>(pageIndex, pageSize));

        Map<String, Object> map = new HashMap<>(3);
        map.put("total_page", productDOPage.getPages());
        map.put("total_record", productDOPage.getTotal());
        map.put("data", productDOPage.getRecords().stream().map(obj -> {
            ProductVO vo = new ProductVO();
            BeanUtil.copyProperties(obj, vo);
            vo.setStock(obj.getStock() - obj.getLockStock());
            return vo;
        }).collect(Collectors.toList()));
        return map;
    }

    @Override
    public ProductVO findDetail(long productID) {
        ProductDO res = productMapper.selectById(productID);
        if (res == null) {
            throw new CustomException(HttpStatus.NOT_FOUND, "(id = " + productID + ") does not exist");
        }
        ProductVO vo = new ProductVO();
        BeanUtil.copyProperties(res, vo);
        return vo;
    }

    @Override
    public Map<Long, ProductVO> findProductsBatchById(List<Long> productIdList) {
        return baseMapper.selectList(new QueryWrapper<ProductDO>().in("id", productIdList)).stream().map(obj -> {
            ProductVO vo = new ProductVO();
            BeanUtil.copyProperties(obj, vo);
            return vo;
//        }).collect(Collectors.toMap(ProductVO::getId, obj -> obj));//等同于下方
        }).collect(Collectors.toMap(ProductVO::getId, Function.identity()));
    }
}
